package org.wheel.plugins.toolkit.sql.enums;

import cn.hutool.core.util.StrUtil;
import lombok.Getter;

/**
 * SQL语法类型：
 * 1. R2dbc-属性值（默认），sql中使用占位符“:propertyName”的方式
 * 2. R2dbc-数字占位符，sql中使用占位符“$数字”的方式
 * 3. 原生SQL-问号占位符，sql中使用问号“?”的方式
 * 4. Mybatis-属性占位符，sql中使用占位符“#{propertyName}”的方式
 * 5. 直接将SQL和参数拼接到SQL中
 * <a href="https://docs.spring.io/spring-data/relational/reference/r2dbc/query-methods.html">R2dbc官方文档</a>
 */

@Getter
public enum SqlModel {

    /**
     * JDBC支持的SQL方式，需要基于spring-jdbc或者r2dbc实现SQL的执行
     * 参考对象：JdbcNamedParameter
     */
    PROPERTY_NAME(1, "属性值", "R2dbc-属性值", ":%s", ":{}"),
    /**
     * R2DBC支持的SQL方式，需要基于spring-r2dbc实现SQL的执行
     */
    NUMBER(2, "数字占位符", "R2dbc-数字占位符", "$%d", "${}"),
    /**
     * 标准原生SQL，参考对象：JdbcParameter
     */
    NATIVE(3, "问号占位符", "原生SQL-问号占位符", "?", "?"),
    /**
     * 参考对象：Mybatis，可以自己实现一个MybatisParameter。
     * {@code CCJSqlParserUtil.parse()}方法，并不能解析当前SQL
     *
     */
    MYBATIS(4, "属性占位符", "Mybatis-属性占位符", "#{%s}", "#{}"),
    DIRECT_SQL(5, "直接将SQL和参数拼接到SQL中", "直接将SQL和参数拼接到SQL中", null, null),
    CUSTOM_0(6, "自定义属性占位符`{}`", "自定义属性占位符`{}`", "{%s}", "{}"),
    CUSTOM_1(6, "自定义属性占位符`{}`", "自定义属性占位符`{}`", "${%s}", "${{}}"),
    ;
    private final int value;
    private final String name;
    private final String description;
    private final String sqlFormat; // String.format(":%s", "p0")
    private final String format; // StrUtil.format("${}", "p0")

    SqlModel(int value, String name, String sqlFormat, String format) {
        this(value, name, name, sqlFormat, format);
    }

    SqlModel(int value, String name, String description, String sqlFormat, String format) {
        this.value = value;
        this.name = name;
        this.description = description;
        this.sqlFormat = sqlFormat;
        this.format = format;
    }

    /**
     * 默认使用属性值
     * <pre>{@code
     * PROPERTY_NAME(1, "属性值", "R2dbc-属性值", ":%s"), // 参考对象：JdbcNamedParameter
     * }</pre>
     * @return
     */
    public static SqlModel getDefaultModel(){
        return PROPERTY_NAME;
    }

    /**
     * 渲染一个占位符
     * @param key 参数名或序号
     * @return 渲染后的占位符
     */
    public String render(String key) {
        if (this == NATIVE) return "?";
        if (this == NUMBER) return "$" + key;
        return StrUtil.format(this.format, key);
    }
}
